# !/usr/bin/env python
# -*-coding:utf-8 -*-

"""
# Author     ：skyTree
# version    ：python 3.11
# Description：角色的curd
"""
from core.Utils import build_tree
from models.base import Role, Menu
from schemas.role import RoleSchema, RoleEditSchema, RoleSetOrDelPermissionSchema, MenuSchema, RoleCreateSchema
from fastapi import HTTPException
from typing import List


async def get_role_menus(obj: object) -> List[MenuSchema]:
    menus_list = [MenuSchema(id=menu.id, name=menu.name, level=menu.level, path=menu.path, pid=menu.pid_id) for menu in
                  obj.menus]
    return menus_list


async def add_role_curd(role: RoleCreateSchema) -> RoleSchema:
    result = await Role.exists(name=role.name)
    if result:
        raise HTTPException(status_code=422, detail="角色已存在！")
    role_obj = await Role.create(name=role.name, desc=role.desc)
    if not role_obj:
        raise HTTPException(status_code=400, detail="添加角色失败！")
    # 使用 .fetch_related() 获取相关联的菜单
    await role_obj.fetch_related("menus")
    # 创建一个新的 RoleSchema 对象，并将角色对象的属性复制到该对象中
    role_data = RoleSchema(**dict(role_obj), menus=await get_role_menus(role_obj))
    return role_data


async def update_role_curd(role: RoleEditSchema) -> RoleSchema:
    update_role = await Role.get_or_none(id=role.id).prefetch_related("menus")
    if not update_role:
        raise HTTPException(status_code=422, detail="角色不存在！")
    if update_role.name != role.name:
        result = await Role.exists(name=role.name)
        if result:
            raise HTTPException(status_code=422, detail="角色已存在！")
    try:
        await update_role.update_from_dict(role.dict())
        await update_role.save()
    except Exception as e:
        raise HTTPException(status_code=500, detail="编辑角色失败！")
    return RoleSchema(**dict(update_role), menus=await get_role_menus(update_role))


async def set_role_permission_curd(post: RoleSetOrDelPermissionSchema) -> RoleSchema:
    role = await Role.get_or_none(id=post.id).prefetch_related("menus")
    if not role:
        raise HTTPException(status_code=422, detail="角色不存在！")
    if len(set(post.mids)) != len(post.mids):
        raise HTTPException(status_code=422, detail="不允许重复设置菜单！")
    menu_list = []
    for i in post.mids:
        if not await Menu.get_or_none(id=i):
            raise HTTPException(status_code=422, detail="该级菜单不存在！")
        menu_list.append(await Menu.get(id=i))
    try:
        await role.menus.clear()
        await role.menus.add(*menu_list)
        await role.save()
        await role.fetch_related("menus")
        menus = [MenuSchema(**dict(menu)).dict() for menu in role.menus]
        menus_tree = build_tree(menus)
        return RoleSchema(id=role.id, name=role.name, desc=role.desc, menus=menus_tree)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"设置权限失败！失败原因：{e}")


async def del_role_permission_curd(post: RoleSetOrDelPermissionSchema) -> RoleSchema:
    role = await Role.get_or_none(id=post.id).prefetch_related("menus")
    if not role:
        raise HTTPException(status_code=422, detail="角色不存在！")
    if len(set(post.mids)) != len(post.mids):
        raise HTTPException(status_code=422, detail="不允许重复设置菜单！")
    menu_list = []
    for i in post.mids:
        if not await Menu.get_or_none(id=i):
            raise HTTPException(status_code=422, detail="该级菜单不存在！")
        if i not in [menu.id for menu in role.menus]:
            raise HTTPException(status_code=422, detail="该角色下没有此菜单！")
        menu_list.append(await Menu.get(id=i))
    try:
        await role.menus.remove(*menu_list)
        await role.save()
        # 此时重新获取关联菜单权限防止没有跟新
        await role.fetch_related("menus")
        menus = [MenuSchema(**dict(menu)).dict() for menu in role.menus]
        menus_tree = build_tree(menus)
        return RoleSchema(id=role.id, name=role.name, desc=role.desc, menus=menus_tree)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"设置权限失败！失败原因：{e}")
